%{
	#include <stdio.h>
	#include <stdlib.h>
	#include <string.h>
	#include "../tableSymbole/hashTable.h"
	#include "tableGencode.h"
	#include "tableValueText.h"
	#include "genMips.h"
	
	extern FILE* yyin;
	FILE* yyout;
	entree temporaire;
	char * bufferItoA;
	int erreurCompilation;
	int boolTemp;
	int nbSysTemp;
	char * charTemp1;
	char * charTemp2;
	int intTemp1;
%}

%token ENTIER PLUS FOIS PGAUCHE PDROITE IDENTIFIANT POINTVIRGULE AFFECTATION WRITE VAR DEUXPOINTS INT MOINS
%start debut
%left PLUS
%left FOIS
%left PGAUCHE
%left topNiveau0
%left topNiveau1

%%
debut : listdecla  listinstr
	;
listdecla : decla POINTVIRGULE listdecla
	|
	;
decla : VAR IDENTIFIANT DEUXPOINTS INT
		{
			ajoutEntreeHashTable(nouvelleEntreeCteInt(tableValueText[$2], 0));
			suppressionTableValueText($2);
		}
	;
listinstr : instr POINTVIRGULE listinstr
	|
	;
instr : IDENTIFIANT AFFECTATION	E
		{/*
			if(!existeMotClefHashTableHorsVide(tableValueText[$1]))
			{
				printf("Erreur : Yacc : identifiant non declare (%s).\n",tableValueText[$1]);
				erreurCompilation = 1;
			}
			else
			{
				bufferItoA = calloc (16, sizeof(char));
				sprintf(bufferItoA,"%d",$3);
				ajoutTableGencode("affectationVal",tableValueText[$1],bufferItoA,"");
			}
			
			suppressionTableValueText($1);
			*/
			
			
			if(pileStructure[nbPileStructure-1] == NULL)
			{
				printf("\tpas de tete de pile\n");
			}
			else
			{
				printf("\ttype tete pile %d\n",pileStructure[nbPileStructure-1]->type);
			}
			if(pileStructure[nbPileStructure-1] == NULL || pileStructure[nbPileStructure-1]->type != PILESTRUCTURE_TYPE_ID)
			{
				printf("Erreur : Yacc : instr -> id := E : E n'est pas un identifiant.\n");
				erreurCompilation = 1;
			}
			else
			{
				charTemp1 = ((structureID)(pileStructure[nbPileStructure-1]->valeur))->nom;
				suppressionTetePileStructure();
				printf("\trécupération de %s dans la pileStructure\n",charTemp1);
				
				intTemp1 = ajoutTableGencode("affectation",tableValueText[$1],charTemp1,"");
				suppressionTableValueText($1);
				printf("\tajout (%d) : %s %s, %s, %s\n",intTemp1, tableGencode[intTemp1]->commande,tableGencode[intTemp1]->adresse1,tableGencode[intTemp1]->adresse2,tableGencode[intTemp1]->adresse3);
				
				//ajoutPileStructure((void *) nouvelleStructureInstr());
			}
		}
	| WRITE IDENTIFIANT
		{
			/*
			if(!existeMotClefHashTableHorsVide(tableValueText[$1]))
			{
				printf("Erreur : Yacc : identifiant non declare (%s).\n",tableValueText[$1]);
				erreurCompilation = 1;
			}
			else
			{
				ajoutTableGencode("ecriture",tableValueText[$1],"","");
			}
				
			suppressionTableValueText($1);
			*/
			
			
			ajoutTableGencode("ecriture",tableValueText[$2],"","");
			suppressionTableValueText($2);
			
			//ajoutPileStructure((void *) nouvelleStructureInstr());
		}
	| WRITE ENTIER
		{
			bufferItoA = calloc (16, sizeof(char));
			sprintf(bufferItoA,"%d",$2);
			ajoutTableGencode("ecritureVal",bufferItoA,"","");
			
			//ajoutPileStructure((void *) nouvelleStructureInstr());
		}
	;
	
E 	: E op2E
		{//E -> E1 * E2					
			//générer une varaible temporaire pour E
			bufferItoA = calloc (16, sizeof(char));
			sprintf(bufferItoA,"_SysTemp%d",nbSysTemp);
			ajoutEntreeHashTable(nouvelleEntreeCteInt(bufferItoA, 0));
			nbSysTemp++;
			printf("\t%s var temp\n",bufferItoA);
			
			if(pileStructure[nbPileStructure-1] == NULL)
			{
				printf("\tpas de tete de pile\n");
			}
			else
			{
				printf("\ttype tete pile %d\n",pileStructure[nbPileStructure-1]->type);
			}
			if(pileStructure[nbPileStructure-1] == NULL || pileStructure[nbPileStructure-1]->type != PILESTRUCTURE_TYPE_ID)
			{
				printf("Erreur : Yacc : E -> E1 +/* E2 : E1 n'est pas un identifiant.\n");
				erreurCompilation = 1;
			}
			else
			{								
				charTemp1 = ((structureID)pileStructure[nbPileStructure-1]->valeur)->nom;
				suppressionTetePileStructure();
				printf("\trécupération de %s dans la pileStructure\n",charTemp1);
				
				if(!existeMotClefHashTableHorsVide(charTemp1))
				{
					printf("Erreur : Yacc : E -> E1 +/* E2 : E1 : identifiant non declare (%s).\n",charTemp1);
					erreurCompilation = 1;
				}
				else
				{
					tableGencode[$2]->adresse1 = bufferItoA;
					tableGencode[$2]->adresse2 = charTemp1;
					printf("\tajout infos à %d : %s %s, %s, %s\n",$2, tableGencode[$2]->commande,tableGencode[$2]->adresse1,tableGencode[$2]->adresse2,tableGencode[$2]->adresse3);
					
					ajoutPileStructure((void *) nouvelleStructureID(bufferItoA), PILESTRUCTURE_TYPE_ID);
					printf("\tajout pile %s\n",bufferItoA);	
					
				}
			}
		}
	| MOINS E 
		{//E -> - E1					
			//générer une varaible temporaire pour E
			bufferItoA = calloc (16, sizeof(char));
			sprintf(bufferItoA,"_SysTemp%d",nbSysTemp);
			ajoutEntreeHashTable(nouvelleEntreeCteInt(bufferItoA, 0));
			nbSysTemp++;
			printf("\t%s var temp\n",bufferItoA);
			
			if(pileStructure[nbPileStructure-1] == NULL)
			{
				printf("\tpas de tete de pile\n");
			}
			else
			{
				printf("\ttype tete pile %d\n",pileStructure[nbPileStructure-1]->type);
			}
			if(pileStructure[nbPileStructure-1] == NULL || pileStructure[nbPileStructure-1]->type != PILESTRUCTURE_TYPE_ID)
			{
				printf("Erreur : Yacc : E -> - E1 : E1 n'est pas un identifiant.\n");
				erreurCompilation = 1;
			}
			else
			{								
				charTemp1 = ((structureID)pileStructure[nbPileStructure-1]->valeur)->nom;
				suppressionTetePileStructure();
				printf("\trécupération de %s dans la pileStructure\n",charTemp1);
				
				if(!existeMotClefHashTableHorsVide(charTemp1))
				{
					printf("Erreur : Yacc : E -> - E1 : E1 : identifiant non declare (%s).\n",charTemp1);
					erreurCompilation = 1;
				}			
				else
				{
					intTemp1 = ajoutTableGencode("moinsUnaire",bufferItoA,charTemp1,"");
					printf("\tajout (%d) : %s %s, %s, %s\n",intTemp1, tableGencode[intTemp1]->commande,tableGencode[intTemp1]->adresse1,tableGencode[intTemp1]->adresse2,tableGencode[intTemp1]->adresse3);
					
					ajoutPileStructure((void *) nouvelleStructureID(bufferItoA), PILESTRUCTURE_TYPE_ID);
					printf("\tajout pile %s\n",bufferItoA);
				}
			}
		}
		%prec topNiveau0
	| PGAUCHE E PDROITE 
		{
			//on fait rien -> recopie
		}
	| IDENTIFIANT 
		{
			ajoutPileStructure((void *) nouvelleStructureID(tableValueText[$1]), PILESTRUCTURE_TYPE_ID);
			printf("\tajout pile %s\n",tableValueText[$1]);
			suppressionTableValueText($1);
		} 
		%prec topNiveau1
	;
	| ENTIER 
		{
			//générer une varaible temporaire pour E
			bufferItoA = calloc (16, sizeof(char));
			sprintf(bufferItoA,"_SysTemp%d",nbSysTemp);
			ajoutEntreeHashTable(nouvelleEntreeCteInt(bufferItoA, 0));
			nbSysTemp++;
			printf("\t%s var temp\n",bufferItoA);
			
			charTemp1 = calloc (16, sizeof(char));
			sprintf(charTemp1,"%d",$1);
			intTemp1 = ajoutTableGencode("affectationVal",bufferItoA,charTemp1,"");
			printf("\tajout (%d) : %s %s, %s, %s\n",intTemp1,tableGencode[intTemp1]->commande,tableGencode[intTemp1]->adresse1,tableGencode[intTemp1]->adresse2,tableGencode[intTemp1]->adresse3);
			
			ajoutPileStructure((void *) nouvelleStructureID(bufferItoA), PILESTRUCTURE_TYPE_ID);
			printf("\tajout pile %s\n",bufferItoA);
		} 
		%prec topNiveau1
	;
op2E : FOIS E
		{
			if(pileStructure[nbPileStructure-1] == NULL)
			{
				printf("\tpas de tete de pile\n");
			}
			else
			{
				printf("\ttype tete pile %d\n",pileStructure[nbPileStructure-1]->type);
			}
			if(pileStructure[nbPileStructure-1] == NULL || pileStructure[nbPileStructure-1]->type != PILESTRUCTURE_TYPE_ID)
			{
				printf("Erreur : Yacc : E -> E1 * E2 : E2 n'est pas un identifiant.\n");
				erreurCompilation = 1;
			}
			else
			{				
				charTemp1 = ((structureID)pileStructure[nbPileStructure-1]->valeur)->nom;
				suppressionTetePileStructure();
				printf("\trécupération de %s dans la pileStructure\n",charTemp1);
				
				if(!existeMotClefHashTableHorsVide(charTemp1))
				{
					printf("Erreur : Yacc : E -> E1 * E2 : E2 : identifiant non declare (%s).\n",charTemp1);
					erreurCompilation = 1;
				}
				else
				{
					$$ = ajoutTableGencode("multiplication","","",charTemp1);
					printf("\tajout (%d) : %s %s, %s, %s\n",$$,tableGencode[$$]->commande,tableGencode[$$]->adresse1,tableGencode[$$]->adresse2,tableGencode[$$]->adresse3);
				}
			}
		}
	| PLUS E
		{
			if(pileStructure[nbPileStructure-1] == NULL)
			{
				printf("\tpas de tete de pile\n");
			}
			else
			{
				printf("\ttype tete pile %d\n",pileStructure[nbPileStructure-1]->type);
			}
			if(pileStructure[nbPileStructure-1] == NULL || pileStructure[nbPileStructure-1]->type != PILESTRUCTURE_TYPE_ID)
			{
				printf("Erreur : Yacc : E -> E1 + E2 : E2 n'est pas un identifiant.\n");
				erreurCompilation = 1;
			}
			else
			{				
				charTemp1 = ((structureID)pileStructure[nbPileStructure-1]->valeur)->nom;
				suppressionTetePileStructure();
				printf("\trécupération de %s dans la pileStructure\n",charTemp1);
				
				if(!existeMotClefHashTableHorsVide(charTemp1))
				{
					printf("Erreur : Yacc : E -> E1 + E2 : E2 : identifiant non declare (%s).\n",charTemp1);
					erreurCompilation = 1;
				}
				else
				{
					$$ = ajoutTableGencode("addition","","",charTemp1);
					printf("\tajout : %s %s, %s, %s\n",tableGencode[$$]->commande,tableGencode[$$]->adresse1,tableGencode[$$]->adresse2,tableGencode[$$]->adresse3);
				}
			}
		}
	;

	
%%

int yyerror(char * s)
{
	printf("\nErreur : %s\n\n", s);
	return -1;
}

int main (int argc, char ** argv)
{
	nbSysTemp = 0;

	if(argc != 3)
	{
		printf("\nUsage : %s <nom fichier en entrée> <nom fichier en sortie>\n\n",argv[0]);
		exit(-1);
	}	
	
	if ((yyin = fopen(argv[1], "r")) == NULL)
	{                  
		printf("\nErreur : impossible d'ouvrir le fichier %s\n\n", argv[1]);
		exit(-1);
	}
	
	if ((yyout = fopen(argv[2], "w+")) == NULL)
	{
		printf("Erreur : impossible de créer le fichier %s\n", argv[2]);
		exit(-1);          
	}
	
	initVariableADeclarer();
	initTableGencode();
	initHashTable();
	initPiles();
	initPourGestionPile();
	erreurCompilation = 0;
	
	printf("Debut analyse\n");
	yyparse();
	if(!hashTableVide())
	{
		sortieBloc();
	}
	printf("Fin analyse\n");
	
	afficheTableGencode();
	
	if(erreurCompilation)
	{
		printf("Erreur : Yacc : il y a eu des erreurs à la compilation.\n");
		exit(-1);
	}
		
	printf("Debut génération mips\n");
	mipsGeneration(yyout);
	printf("Fin génération mips\n");
	
	fclose(yyin);	
	fclose(yyout);
	
	return 0;
}
